/**
 * 
 */
/**
 * @author gongyo
 *
 */
package org.third.security.crypto;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class FipsCryptoTest {
    static final Logger logger = LoggerFactory.getLogger(FipsCryptoTest.class);
	private static final String KEYSTORE_PASSWORD = null;
	private static final String KEYSTORE_PASS_PROP_NAME = null;
	private static final String KEY_NAME = null;
    static ExternalSecurityProviderHelper crypto;

    /**
     * set the crypto to be used for encryption/decryption
     */
    private void updateCrypto(Properties props) throws IOException {
        String providerName = null;
        String keystore = null;
        String keystorePassword = null;
        String keyAlias = null;
        String encryptedKeyFile = null;
        String encKey = null;
        Integer keySize = null;
        boolean externalProvider = Boolean.parseBoolean(getPropValue(USE_EXTERNAL_PROVIDER, "false", props));
        if (externalProvider) {
            providerName = getPropValue(SECURITY_PROVIDER_NAME, props);
            keySize = Integer.parseInt(props.getProperty(KEY_SIZE, DEFAULT_ENC_ALG_KEY_SIZE));
            keystore = getPropValue(KEYSTORE, props);
            keystorePassword = System.getProperty(KEYSTORE_PASS_PROP_NAME);
            if (keystorePassword == null) {
                keystorePassword = getKeystorePasswordAndDeleteFile(getPropValue(KEYSTORE_PASSWORD_FILE, props));
            }
            keyAlias = getPropValue(KEY_ALIAS, props);

            // retrieve the encrypted key from this file
            if ((encKey = System.getProperty(KEY_NAME)) == null) {
                Properties keyprops = new Properties();
                encryptedKeyFile = getPropValue(ENC_KEY_FILE, props);
                keyprops.load(new FileInputStream(new File(encryptedKeyFile)));
                encKey = new String(keyprops.getProperty(KEY_NAME));
            }

        }
        try {
            // CryptoInterface crypto = PasswordUtil.getEncryptor(externalProvider, providerName,
            // (keySize == null || keySize.trim().equals("")) ? null : new Integer(keySize), keystore,
            // keystorePassword, keyAlias, encryptedKeyFile);
            crypto = new ExternalSecurityProviderHelper(providerName, keySize, keystore, keystorePassword, keyAlias,
                    encryptedKeyFile);
            if (externalProvider) {
                setCrypto(crypto, encKey);
//                crypto.setKeystoreType(props.getProperty("keystoreType"));
                // set trustore properties
                updateJVMProperties(crypto, props);
            }
        } catch (Exception e) {
            logger.error("Exception when initializing the encryptor. " + e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * Set the SSL keystore and truststore for PKCS12 . Thsi methosd is utilized when run in FIPS compliant mode
     */

    private void updateJVMProperties(CryptoInterface crypto, Properties props) throws Exception {
        System.out.println("Setting truststore properties");
        // SSL trustore location
        // System.setProperty(JAVA_SSL_TRUSTSTORE, getPropValue(SSL_TRUSTSTORE_LOCN_PARAM, props));
        // System.setProperty(JAVA_TRUSTSTORE_TYPE_PARAM, KEYSTORE_TYPE_DEFAULT_VALUE);
        // System.setProperty(JAVA_SSL_TRUSTSTORE_PASS, crypto.decrypt(getPropValue(SSL_TRUSTSTORE_PASSWD_PARAM,
        // props)));

    }

    private String getPropValue(String key, String defaultValue, Properties props) {
        return (props.getProperty(key) == null) ? defaultValue : props.getProperty(key);
    }

    private String getPropValue(String key, Properties props) {
        return props.getProperty(key);
    }

    /**
     * Loads the keystore password from a file and deletes the file. The keystore password file contains a line with the
     * following format:
     * 
     * <pre>
     * keystorePassword = password
     * </pre>
     *
     * @param path the file system path to the keystore password file
     *
     * @return the keystore password
     *
     * @throws IOException when the keystore file cannot be read.
     */
    private static String getKeystorePasswordAndDeleteFile(String path) throws IOException {
        Properties keyProps = new Properties();
        File keystorePasswordFile = new File(path);
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(keystorePasswordFile);
            keyProps.load(fis);
        } catch (IOException e) {
            logger.debug("Error reading file at : " + path, e);
            throw e;
        } finally {
            if (fis != null) {
                fis.close();
            }
        }

        String password = keyProps.getProperty(KEYSTORE_PASSWORD);
        System.setProperty(KEYSTORE_PASS_PROP_NAME, password);
        // delete the file
        keystorePasswordFile.delete();
        return password;
    }

    public static void main(String[] args) {
        System.setProperty(KEYSTORE_PASS_PROP_NAME, "tomcat1");
        System.setProperty(KEY_NAME, "cloud");
        FipsCryptoTest ft = new FipsCryptoTest();
        ft.testFips();

    }

    private void testFips() {
        InputStream fis = FipsCryptoTest.class.getResourceAsStream("/org/third/crypto/idm/idm-security.properties");
        try {
//            PropertyValueEncryptionUtils.loadIDMProperty(fis);
//            Properties props = PropertyValueEncryptionUtils.getProperties();
//            updateCrypto(props);

            String encKey = "cloud";
////            String encKeyAsync = crypto.encryptAsymBytes(encKey.getBytes());
//            System.out.println(encKeyAsync);
//            setCrypto(crypto, encKeyAsync);

            String encKeySym = crypto.encrypt("hello");
            System.out.println(encKeySym);
            
            String decKeySym = crypto.decrypt(encKey);
            System.out.println(decKeySym);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
